package 多线程.管程法;

/**
 * @Author zhang lei
 * @Date 2021-11-13 15:23
 * 生产者-消费者 问题， 之管程法
 *
 * 思想：
 * 1.首先需要四个角色 ：1.生产者2.消费者3.缓冲区4.馒头
 * 2.生产者生产馒头放到缓冲区，缓冲区如果满了，生产者停止运作，进入等待
 * 3.消费者从缓冲区拿馒头，如果缓冲区馒头没有了，先唤醒生产者，然后进入等待
 *
 */
class CoTest01 {
    public static void main(String[] args) {
        SynContainer synContainer = new SynContainer();

        new Thread(new Producer(synContainer)).start();
        new Thread(new Comsumer(synContainer)).start();
    }

}

class Producer implements Runnable{

    private SynContainer synContainer;

    private static int i = 0;

    public Producer(SynContainer synContainer) {
        this.synContainer = synContainer;
    }

    @Override
    public void run() {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("开始生产第"+i+"1只🐔" +"，当前数量为"+synContainer.count);
                try {
                    synContainer.push(new Chicken(i++ +1));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    }
}

class Comsumer implements Runnable{

    private SynContainer synContainer;

    public Comsumer(SynContainer synContainer) {
        this.synContainer = synContainer;
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                synContainer.pop();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Chicken {
    int id;
    public Chicken(int id) {
        this.id = id;
    }
}

class SynContainer {

    Chicken[] chickens = new Chicken[10];

    int count;

    public void setCount(int count) {
        this.count = count;
    }

    public synchronized void push(Chicken chicken) throws InterruptedException {
        if(count == chickens.length-1) {
            System.out.println("当前数量为"+count +"生产者在等待");
            this.wait();
        }

        chickens[count] = chicken;
        setCount(count+1);
        this.notifyAll();
    }

    public synchronized Chicken pop() throws InterruptedException {
        if(count == 0) {
            System.out.println("当前数量为"+count +"，消费者在等待");
            this.wait();
        }

        Chicken result = chickens[count];
        setCount(count-1);
        this.notifyAll();
        return result;
    }

}